realmcrafterfandomcom-20200216-history
Adding Scenery and Actor LOD Source Tutorial
Created by Cysis on the RealmCrafter: Community Edition forums. Before starting this tut please backup all your work! Right one of the classic features of RCS's stupidity is trying to Render everything at once. This causes low fps rates and limits the amount of detail you can have in your zones. LOD fixes this and tells your client only to render certain models depending on the players range to them, without affecting certain models for example terrain. Scenery LOD First start by Opening your Client.bb file. Find the section that looks like this... CameraProjMode(GY_Cam, 1) ; Render GUI CameraProjMode(Cam, 0) For S.Scenery = Each Scenery HideEntity(S\EN) Next For T.Terrain = Each Terrain HideEntity(T\EN) Next RenderWorld() CameraProjMode(Cam, 1) For S.Scenery = Each Scenery ShowEntity(S\EN) Next For T.Terrain = Each Terrain ShowEntity(T\EN) Next PostRenderWorld() ; DebugBanner update UpdateFPS() And replace it with.... CameraProjMode(GY_Cam, 1) ; Render GUI CameraProjMode(Cam, 0) For S.Scenery = Each Scenery HideEntity(S\EN) Next For T.Terrain = Each Terrain HideEntity(T\EN) Next RenderWorld() CameraProjMode(Cam, 1) For S.Scenery = Each Scenery ;LOD scenery Select S\SceneryType$ Case "T" ShowEntity(S\EN) Case "B" If EntityDistance#(S\EN, Cam) < BuildingMaxViewDistance# ShowEntity(S\EN) Else HideEntity(S\EN) EndIf Case "G" If EntityDistance#(S\EN, Cam) < GrassMaxViewDistance# ShowEntity(S\EN) Else HideEntity(S\EN) EndIf Case "Z" If EntityDistance#(S\EN, Cam) < ObjectMaxViewDistance# ShowEntity(S\EN) Else HideEntity(S\EN) EndIf Default ShowEntity(S\EN) End Select Next For T.Terrain = Each Terrain ShowEntity(T\EN) Next PostRenderWorld() ; DebugBanner update UpdateFPS() Next open ClientAreas.bb and find... Type Scenery Field SceneryID ; Set by user, used for scenery ownerships Field EN, MeshID Field AnimationMode ; 0 = no animation, 1 = constant animation (loops), 2 = constant (ping-pongs), 3 = animate when selected Field ScaleX#, ScaleY#, ScaleZ# Field Lightmap$ ; Lightmap filename Field RCTE$ ; Used by toolbox editors only Field TextureID ; To alter the texture loaded automatically with the model, if required (65535 to ignore) Field CatchRain Field Locked End Type And add this at the end... Field SceneryType$ ;Variable declaration for view distance Should now look like this... Type Scenery Field SceneryID ; Set by user, used for scenery ownerships Field EN, MeshID Field AnimationMode ; 0 = no animation, 1 = constant animation (loops), 2 = constant (ping-pongs), 3 = animate when selected Field ScaleX#, ScaleY#, ScaleZ# Field Lightmap$ ; Lightmap filename Field RCTE$ ; Used by toolbox editors only Field TextureID ; To alter the texture loaded automatically with the model, if required (65535 to ignore) Field CatchRain Field Locked Field SceneryType$ ;Variable declaration for view distance End Type Under this section add. these are your ranges for the Fade in and Fade out ;LOD (Set view distances here) Const BuildingMinViewDistance# = 230.0 ; If distance < this value will be Visible, else will autofade slowly Const BuildingMaxViewDistance# = 250.0 ; If distance > this value will be 100% invisible Const GrassMinViewDistance# = 75.0 Const GrassMaxViewDistance# = 90.0 Const ObjectMinViewDistance# = 130.0 Const ObjectMaxViewDistance# = 150.0 Should now look like Type Scenery Field SceneryID ; Set by user, used for scenery ownerships Field EN, MeshID Field AnimationMode ; 0 = no animation, 1 = constant animation (loops), 2 = constant (ping-pongs), 3 = animate when selected Field ScaleX#, ScaleY#, ScaleZ# Field Lightmap$ ; Lightmap filename Field RCTE$ ; Used by toolbox editors only Field TextureID ; To alter the texture loaded automatically with the model, if required (65535 to ignore) Field CatchRain Field Locked Field SceneryType$ ;Variable declaration for view distance Ramoida End Type ;LOD (Set view distances here) Const BuildingMinViewDistance# = 230.0 ; If distance < this value will be Visible, else will autofade slowly Const BuildingMaxViewDistance# = 250.0 ; If distance > this value will be 100% invisible Const GrassMinViewDistance# = 75.0 Const GrassMaxViewDistance# = 90.0 Const ObjectMinViewDistance# = 130.0 Const ObjectMaxViewDistance# = 150.0 Next Scroll down and find If S\EN <> 0 ; Toolbox extras If Len(S\RCTE$) > 5 Select Left$(S\RCTE$, 5) Case "_TREE" If DisplayItems = False swingsty = Int(Mid$(S\RCTE$, 6, 1)) evergrn = Int(Mid$(S\RCTE$, 7, 1)) S\EN = LoadTree("", evergrn, S\EN, swingsty) EndIf Case "_GRSS" swingsty = Int(Mid$(S\RCTE$, 6, 1)) evergrn = Int(Mid$(S\RCTE$, 7, 1)) S\EN = LoadGrass("", evergrn, S\EN, swingsty) Case "_RCDN" If DisplayItems = False RotateMesh(S\EN, Pitch#, Yaw#, Roll#) ScaleEntity(S\EN, S\ScaleX#, S\ScaleY#, S\ScaleZ#) ChunkTerrain(S\EN, 3, 3, 3, X#, Y#, Z#) Delete S Goto CancelScenery EndIf End Select EndIf ; Set position/rotation PositionEntity S\EN, X#, Y#, Z# : RotateEntity S\EN, Pitch#, Yaw#, Roll# ScaleEntity S\EN, S\ScaleX#, S\ScaleY#, S\ScaleZ# Underneath it add ;LOD S\SceneryType$ = "" ;initiate the variable just in case If Instr(Name$, "RCTE\") ;these folders wont be affected by LOD, this is so that models that have actors on it wont disappear causing the actors to fall S\SceneryType$ = "T" ;If it is Terrain, mark it as "T" ;This will be used at Client.bb ;;BUILDINGS ElseIf Instr(Name$, "BUILDINGS\") S\SceneryType$ = "B" EntityAutoFade S\EN,BuildingMinViewDistance#,BuildingMaxViewDistance#;If it is an object set autofade ;GRASS ElseIf Instr(Name$, "GRASS\") S\SceneryType$ = "G" EntityAutoFade S\EN, GrassMinViewDistance#, GrassMaxViewDistance# ElseIf Instr(Name$, "OBJECTS\") S\SceneryType$ = "Z" EntityAutoFade S\EN, ObjectMinViewDistance#, ObjectMaxViewDistance# EndIf That section is your file Directories for the different ranges. It has been Set up to already look into your \Data\Meshes folder so you need to add the folders of your models yourself. The way you do this is using Instr(Name$, "FOLDERNAME\") But if you want more than one folder of models affected by that LOD range then simply add. Or Instr(Name$, "FOLDERNAME2\") Next to it on the same line so it looks a bit like Instr(Name$, "FOLDERNAME\") Or Instr(Name$, "FOLDERNAME2\") etc. YOU MUST WRITE FOLDER NAMES IN CAPITALS EVEN IF THEY ARE NOT NAMED WITH CAPITALS also you must have \ at the end of the name or it wont work. Any folder that isn't listed in these three sections simply wont be affected by LOD and will continue to render as usual. I believe thats it for scenery LOD give it a try and please post if it's not working i may have missed something. Actor LOD This one is much simpler to set up. Open your Client.bb and find under Function UpdateActorInstances() SetPickModes() ; Updates for every actor For AI.ActorInstance = Each ActorInstance ; If it's not dead If AI\Attributes\ValueHealthStat > 0 ; Fade in (uses \AIMode field which is a server field, to save adding an extra field and using server memory) ; DISABLE - uses entityautofade instead ; If AI\AIMode < 501 ; If AI = Me Or AI = Me\Mount Then AI\AIMode = 499 ; The player and the player's mount do not fade in ; AI\AIMode = AI\AIMode + 2 ; Alpha# = Float#(AI\AIMode) / 501.0 ; EntityAlpha AI\EN, Alpha# ; EntityAlpha AI\ShadowEN, Alpha# ; If AI\WeaponEN <> 0 Then EntityAlpha AI\WeaponEN, Alpha# ; If AI\ShieldEN <> 0 Then EntityAlpha AI\ShieldEN, Alpha# ; If AI\HatEN <> 0 Then EntityAlpha AI\HatEN, Alpha# ; EndIf ; Check if this actor is underwater AI\Underwater = 0 If AI\Actor\Environment = Environment_Amphibious For W.Water = Each Water If EntityY#(AI\CollisionEN) < EntityY#(W\EN) - 0.5 If Abs(EntityX#(AI\CollisionEN) - EntityX#(W\EN)) < (W\ScaleX# / 2.0) If Abs(EntityZ#(AI\CollisionEN) - EntityZ#(W\EN)) < (W\ScaleZ# / 2.0) AI\Underwater = Handle(W) PositionEntity(AI\EN, 0, 0, 0) Exit EndIf EndIf EndIf Next EndIf If AI\Underwater = 0 Then PositionEntity(AI\EN, 0, MeshHeight#(AI\EN) / -2.0, 0) Under this add EntityAutoFade(AI\EN),55,65 ; adjust these for range values Min,Max If EntityDistance(AI\EN,cam) > (50) HideEntity(AI\EN) ElseIf EntityDistance(AI\EN,cam) <(45) ShowEntity(AI\EN) EndIf Should now look like Function UpdateActorInstances() SetPickModes() ; Updates for every actor For AI.ActorInstance = Each ActorInstance ; If it's not dead If AI\Attributes\ValueHealthStat > 0 ; Fade in (uses \AIMode field which is a server field, to save adding an extra field and using server memory) ; DISABLE - uses entityautofade instead ; If AI\AIMode < 501 ; If AI = Me Or AI = Me\Mount Then AI\AIMode = 499 ; The player and the player's mount do not fade in ; AI\AIMode = AI\AIMode + 2 ; Alpha# = Float#(AI\AIMode) / 501.0 ; EntityAlpha AI\EN, Alpha# ; EntityAlpha AI\ShadowEN, Alpha# ; If AI\WeaponEN <> 0 Then EntityAlpha AI\WeaponEN, Alpha# ; If AI\ShieldEN <> 0 Then EntityAlpha AI\ShieldEN, Alpha# ; If AI\HatEN <> 0 Then EntityAlpha AI\HatEN, Alpha# ; EndIf ; Check if this actor is underwater AI\Underwater = 0 If AI\Actor\Environment = Environment_Amphibious For W.Water = Each Water If EntityY#(AI\CollisionEN) < EntityY#(W\EN) - 0.5 If Abs(EntityX#(AI\CollisionEN) - EntityX#(W\EN)) < (W\ScaleX# / 2.0) If Abs(EntityZ#(AI\CollisionEN) - EntityZ#(W\EN)) < (W\ScaleZ# / 2.0) AI\Underwater = Handle(W) PositionEntity(AI\EN, 0, 0, 0) Exit EndIf EndIf EndIf Next EndIf If AI\Underwater = 0 Then PositionEntity(AI\EN, 0, MeshHeight#(AI\EN) / -2.0, 0) EntityAutoFade(AI\EN),55,65 If EntityDistance(AI\EN,cam) > (50) HideEntity(AI\EN) ElseIf EntityDistance(AI\EN,cam) <(45) ShowEntity(AI\EN) EndIf ; Show/hide nametags in HideNametags mode 2 (selected only) If HideNametags = 2 If AI\NametagEN <> 0 If Handle(AI) = PlayerTarget ShowEntity(AI\NametagEN) Else HideEntity(AI\NametagEN) EndIf EndIf EndIf And thats it. Again post if you get a MAV so that it can be fixed for everyone! Save everything and compile an .Exe and try it out!